package cn.slipi.admin.biz;

import cn.slipi.admin.biz.vo.menu.AuthMenuVo;
import cn.slipi.admin.biz.vo.menu.ItemMenuVo;
import cn.slipi.admin.biz.vo.menu.MenuVo;
import cn.slipi.admin.common.utils.cache.redis.RedisClient;
import cn.slipi.admin.common.utils.dozer.impl.ConvertBean;
import cn.slipi.admin.context.AdminThreadContext;
import cn.slipi.admin.context.AdminVisitor;
import cn.slipi.admin.context.dto.Menu;
import cn.slipi.admin.context.dto.VisitorInfo;
import cn.slipi.admin.controller.form.menu.MenuSaveForm;
import cn.slipi.admin.entity.TSysMenu;
import cn.slipi.admin.entity.TSysRoleMenu;
import cn.slipi.admin.service.TSysMenuService;
import cn.slipi.admin.service.dto.in.m.MenuSaveDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 菜单业务层
 *
 * @author lee
 * @date 2019-03-17
 * @since 1.0.0
 */
@Component
public class MenuBiz {

    @Autowired
    private ConvertBean convertBean;

    @Autowired
    private RedisClient redisClient;

    @Autowired
    private TSysMenuService sysMenuService;


    private final static Logger LOG = LoggerFactory.getLogger(MenuBiz.class);

    public List<MenuVo> getMenuListTree() {
        //获取登陆用户拥有的菜单
        AdminVisitor visitor = AdminThreadContext.getApiVisitor();
        List<Integer> curMenuIds = new ArrayList<>();
        if (visitor != null) {
            String token = visitor.getToken();
            VisitorInfo visitorInfo = this.redisClient.get(token, VisitorInfo.class);
            List<Menu> menuDTOList = visitorInfo.getMenus();
            if (null != menuDTOList) {
                curMenuIds = menuDTOList.stream().map(Menu::getId).collect(Collectors.toList());
            }
        }
        List<MenuVo> menuVoList = new ArrayList<>();
        //顶级菜单getMenuByLevelAndIds
        List<TSysMenu> topMenuList = new ArrayList<>();
        if (null != visitor && null != visitor.getVisitorInfo() && visitor.getVisitorInfo().getIsAdmin().equals(1)) {
            topMenuList = this.sysMenuService.getMenuByLevel(0, 1);
        } else {
            if (curMenuIds.size() > 0) {
                topMenuList = this.sysMenuService.getMenuByLevelAndIds(0, curMenuIds, 1);
            } else {
                return new ArrayList<>();
            }
        }
        //顶级菜单id，子菜单父id
        List<Integer> pids = topMenuList.stream().map(TSysMenu::getId).collect(Collectors.toList());
        //二级菜单
        List<TSysMenu> secondMenuList = new ArrayList<>();
        if (visitor.getVisitorInfo().getIsAdmin().equals(1)) {
            secondMenuList = this.sysMenuService.getMenuByPids(pids, 1);
        } else {
            secondMenuList = this.sysMenuService.getMenuByPidsAndIds(pids, curMenuIds, 1);
        }
        //根据父级ID分组
        Map<Integer, List<TSysMenu>> secondMenuGroup = secondMenuList.stream().collect(Collectors.groupingBy(TSysMenu::getPid));

        //构造菜单结构
        topMenuList.forEach(topMenu -> {
            MenuVo menuVo = new MenuVo();
            if (secondMenuGroup.containsKey(topMenu.getId())) {
                List<TSysMenu> mapMenuList = secondMenuGroup.get(topMenu.getId());
                List<ItemMenuVo> itemMenuVoList = this.convertBean.convert(mapMenuList, ItemMenuVo.class);
                menuVo.setList(itemMenuVoList);
            } else {
                menuVo.setList(new ArrayList<>());
            }
            this.convertBean.convert(topMenu, menuVo);
            menuVoList.add(menuVo);
        });
        return menuVoList;
    }


    public List<AuthMenuVo> getMenuListAuth(Integer rid) {
        List<AuthMenuVo> authMenuVoListParent = new ArrayList<>();
        //顶级菜单
        List<TSysMenu> topMenuList = this.sysMenuService.getMenuByLevel(0, 0);
        //顶级菜单id，子菜单父id
        List<Integer> pids = topMenuList.stream().map(TSysMenu::getId).collect(Collectors.toList());
        //二级菜单
        List<TSysMenu> secondMenuList = this.sysMenuService.getMenuByPids(pids, 0);
        //根据父级ID分组
        Map<Integer, List<TSysMenu>> secondMenuGroup = secondMenuList.stream().collect(Collectors.groupingBy(TSysMenu::getPid));
        //获取当前角色菜单
        List<TSysRoleMenu> roleMenuList = this.sysMenuService.getRoleMenuListByRoleId(rid);
        List<Integer> curMenuIds = new ArrayList<>();
        if (roleMenuList.size() > 0) {
            curMenuIds = roleMenuList.stream().map(TSysRoleMenu::getMenuId).collect(Collectors.toList());
        }
        List<Integer> fCurMenuIds = curMenuIds;
        //构造菜单结构
        topMenuList.forEach(topMenu -> {
            AuthMenuVo authMenuVoParent = new AuthMenuVo();
            if (secondMenuGroup.containsKey(topMenu.getId())) {
                List<TSysMenu> mapMenuList = secondMenuGroup.get(topMenu.getId());
                List<AuthMenuVo> authMenuVoListChild = new ArrayList<>();
                mapMenuList.forEach(menu -> {
                    AuthMenuVo authMenuVoChild = new AuthMenuVo();
                    authMenuVoChild = menuMapAuthMenu(menu, fCurMenuIds, authMenuVoChild);
                    authMenuVoListChild.add(authMenuVoChild);
                });
                authMenuVoParent.setChildren(authMenuVoListChild);
            }
            authMenuVoParent = menuMapAuthMenu(topMenu, fCurMenuIds, authMenuVoParent);
            authMenuVoListParent.add(authMenuVoParent);
        });
        return authMenuVoListParent;
    }

    private AuthMenuVo menuMapAuthMenu(TSysMenu menu, List<Integer> menuIds, AuthMenuVo authMenuVoParent) {
        AuthMenuVo authMenuVo = new AuthMenuVo();
        authMenuVo.setId(menu.getId());
        authMenuVo.setLevel(menu.getLevel());
        authMenuVo.setTitle(menu.getTitle());
        authMenuVo.setParentId(menu.getPid());
        List<Map<String, String>> checkArr = new ArrayList<>();
        Map<String, String> check = new HashMap<>();
        if (null != authMenuVoParent.getChildren() && authMenuVoParent.getChildren().size() > 0) {
            List<AuthMenuVo> authMenuVoList = authMenuVoParent.getChildren();
            boolean isCheck = false;
            for (AuthMenuVo child : authMenuVoList) {
                List<Map<String, String>> mapList = child.getCheckArr();
                if (mapList.size() > 0) {
                    Map<String, String> checkMap = mapList.get(0);
                    if ("1".equals(checkMap.get("isChecked"))) {
                        isCheck = true;
                    }
                }
            }
            if (isCheck) {
                check.put("isChecked", "1");
            } else {
                check.put("isChecked", "0");
            }
            check.put("type", "0");
            authMenuVo.setIsLast(false);
        } else {
            if (menuIds.contains(menu.getId())) {
                check.put("type", "0");
                check.put("isChecked", "1");
            } else {
                check.put("type", "0");
                check.put("isChecked", "0");
            }
            authMenuVo.setIsLast(true);
        }
        checkArr.add(check);
        authMenuVo.setCheckArr(checkArr);
        authMenuVo.setChildren(authMenuVoParent.getChildren());
        return authMenuVo;
    }

    /**
     * 获取所有菜单
     *
     * @return
     */
    public List<TSysMenu> getMenuList() {
        return this.sysMenuService.getMenuList(0);
    }

    /**
     * 获取顶级菜单
     *
     * @return
     */
    public List<TSysMenu> getTopMenuList() {
        return this.sysMenuService.getMenuByLevel(0, 0);
    }


    /**
     * 添加菜单
     *
     * @param menuSaveForm
     * @return
     */
    public Integer addMenu(MenuSaveForm menuSaveForm) {
        MenuSaveDTO menuSaveDto = this.convertBean.convert(menuSaveForm, MenuSaveDTO.class);
        return this.sysMenuService.addMenu(menuSaveDto);
    }

    /**
     * 更新菜单
     *
     * @param mid
     * @param menuSaveForm
     * @return
     */
    public Boolean updateMenu(Integer mid, MenuSaveForm menuSaveForm) {
        MenuSaveDTO menuSaveDto = this.convertBean.convert(menuSaveForm, MenuSaveDTO.class);
        return this.sysMenuService.updateMenu(mid, menuSaveDto);
    }

    /**
     * 删除菜单
     *
     * @param mid
     * @return
     */
    public Boolean deleteMenu(Integer mid) {
        return this.sysMenuService.deleteMenu(mid);
    }

}
